package com.brayan.webapp.controller.general;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;

import org.apache.log4j.Logger;

import com.brayan.webapp.model.general.country.Country;
import com.brayan.webapp.model.general.geoinfo.GeoInfo;
import com.brayan.webapp.repository.general.country.CountryRepository;
import com.brayan.webapp.service.general.currencyconversion.CurrencyBean;
import com.brayan.webapp.service.general.geoinfo.GeoIPBean;

@Named
@Path("/")
@Consumes({ "application/json" })
@Produces({ "application/json" })
public class CurrencyResource {

	private static final String DEFAULT_CURRENCY = "EUR";
	/** Ensure that we don't pay extra */
	private static final double MARGIN_FACTOR = 1.01;

	private static Logger LOGGER = Logger.getLogger(CurrencyResource.class);

	@Inject
	private CurrencyBean currencyService;
	@Inject
	private GeoIPBean geoIpService;
	@Inject
	private CountryRepository countryRepoService;

	/**
	 * Return a default list of provided currencies to convert from EUR.
	 * 
	 * @param amount
	 * @return Returns a list of non-selected conversion.
	 */
	@GET
	@Path("general/currency/{amount}")
	public List<CurrencyConversion> getConvertedCurrencies(@PathParam("amount") int amount,
			@Context HttpServletRequest request) {

		List<CurrencyConversion> currencyConversionList = new ArrayList<CurrencyConversion>();

		String ipAddress = null;
		try {
			ipAddress = request.getHeader("X-FORWARDED-FOR");
			if (ipAddress == null)
				ipAddress = request.getRemoteAddr();
		} catch (Exception ex) {
			LOGGER.error("Failed to retrieve ip Address from servlet request object. " + ex.getMessage());
			throw ex;
		}

		try {
			CurrencyConversion curLocal = convertToCurrency(amount, getCurrencyCodeByIpAddress(ipAddress));
			if (curLocal != null) {
				currencyConversionList.add(curLocal);
			} else {
				LOGGER.error("Retrieved a null object (CurrencyConversion) by IP " + ipAddress + ".");
			}
		} catch (Exception ex) {
			LOGGER.error("Failed to retrieve local currency code by IP address " + ipAddress + ". " + ex.getMessage());
		}

		// CurrencyConversion curCHF = convertToCurrency(amount, "CHF");
		// CurrencyConversion curGBP = convertToCurrency(amount, "GBP");
		// CurrencyConversion curUSD = convertToCurrency(amount, "USD");
		// currencyConversionList.add(curCHF);
		// currencyConversionList.add(curGBP);
		// currencyConversionList.add(curUSD);

		return currencyConversionList;
	}

	/**
	 * Return the currency fetched by IP address.
	 * 
	 * @param ipAddress
	 * @return
	 */
	private String getCurrencyCodeByIpAddress(String ipAddress) {
		LOGGER.info("Attempting to grasp currency with IP address " + ipAddress + ".");
		Country country = null;

		GeoInfo geoInfo = null;
		try {
			geoInfo = geoIpService.getGeoInfoByIp(ipAddress);
			if (geoInfo == null) {
				LOGGER.error("Retrieved null object (GeoInfo) by ipAddress (" + ipAddress + ").");
			}
		} catch (Exception ex) {
			LOGGER.error("Failed to retrieve geo info by ipAddress (" + ipAddress + ").", ex);
			return null;
		}

		try {
			if (geoInfo != null)
				country = countryRepoService.findCountryByCode(geoInfo.getCountryCode());
			if (country == null)
				return null;
		} catch (Exception ex) {
			LOGGER.error(
					"Failed to retrieve corresponding country from the DB with country code "
							+ geoInfo.getCountryCode() + ".", ex);
			return null;
		}

		return country.getCurrencyCode();
	}

	@GET
	@Path("general/currency/{amount}/{currencyToConvertTo}")
	public CurrencyConversion getConvertedCurrencies(@PathParam("amount") int amount,
			@PathParam("currencyToConvertTo") String currencyToConvertTo) {
		return null;
	}

	private CurrencyConversion convertToCurrency(double amount, String targetCurrency) {
		if (targetCurrency == null)
			return null;
		double convRate = currencyService.getConversionRate(DEFAULT_CURRENCY, targetCurrency);

		CurrencyConversion currencyCon = new CurrencyConversion();
		currencyCon.setAmount(Math.round(amount * convRate * MARGIN_FACTOR));
		currencyCon.setCurrency(DEFAULT_CURRENCY);
		currencyCon.setTargetCurrency(targetCurrency);
		return currencyCon;
	}
}